package com.hmdp.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.hmdp.dto.Result;
import com.hmdp.utils.SystemConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Slf4j
@RestController
@RequestMapping("upload")
public class UploadController {

    @PostMapping("/blog")
    public Result uploadImage(@RequestParam("file") MultipartFile image) {
        try {
            // 获取原始文件名称
            String originalFilename = image.getOriginalFilename();
            // 生成新文件名
            String fileName = createNewFileName(originalFilename);
            // 保存文件
            image.transferTo(new File(SystemConstants.IMAGE_UPLOAD_DIR, fileName));
            // 返回结果
            log.debug("文件上传成功，{}", fileName);
            return Result.ok(fileName);
        } catch (IOException e) {
            throw new RuntimeException("文件上传失败", e);
        }
    }

    @GetMapping("/blog/delete")
    public Result deleteBlogImg(@RequestParam("name") String filename) {
        File file = new File(SystemConstants.IMAGE_UPLOAD_DIR, filename);
        if (file.isDirectory()) {
            return Result.fail("错误的文件名称");
        }
        FileUtil.del(file);
        return Result.ok();
    }

    /**
     hash & 0xF
     这行代码执行的是按位与（bitwise AND）操作。&操作符会对hash和0xF的每一位进行比较，只有当两个对应的位都为1时，
     结果位才为1，否则为0。由于0xF在二进制中表示为0000 1111，这个操作实际上是在提取hash的低4位（即从右往左数的前4位）。
     这是因为0xF的左边（高位）都是0，所以与任何数进行按位与时，都不会改变那些位，而只会影响与0xF中1对应的位。
     (hash >> 4) & 0xF
     这行代码首先执行了右移（right shift）操作hash >> 4，即将hash的每一位都向右移动4位。这相当于丢弃了hash的低4位，
     而将原本的高4位及其右边的所有位都向左移动了4位。然后，再对这个右移后的结果执行按位与操作& 0xF，与上面相同，
     这实际上是提取了右移后结果的低4位。由于之前进行了右移操作，所以这里提取的是hash中原本的第5位到第8位（即从右往左
     数的第5个到第8个比特位）。
     * @param originalFilename
     * @return
     */
    private String createNewFileName(String originalFilename) {
        // 获取后缀
        String suffix = StrUtil.subAfter(originalFilename, ".", true);
        // 生成目录
        String name = UUID.randomUUID().toString();
        int hash = name.hashCode();
        // 生成目录 0-15
        int d1 = hash & 0xF;
        // 生成目录 16-31
        int d2 = (hash >> 4) & 0xF;
        // 判断目录是否存在
        File dir = new File(SystemConstants.IMAGE_UPLOAD_DIR, StrUtil.format("/blogs/{}/{}", d1, d2));
        if (!dir.exists()) {
            dir.mkdirs();
        }
        // 生成文件名
        return StrUtil.format("/blogs/{}/{}/{}.{}", d1, d2, name, suffix);
    }
}
